package dk.eclipse.android.badassapp.helper;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.util.FloatMath;
import dk.eclipse.android.badassapp.contact.ContactsHelper;
import dk.eclipse.android.badassapp.distance.GeocodedAddressChoiceList;
import dk.eclipse.android.badassapp.location.MyLocationManagerImpl;
import dk.eclipse.android.badassapp.preferences.PreferenceHelper;

/**
 * This helper handles typical location operations.
 * 
 * @author Ronni Kahalani
 * 
 */
public class LocationHelper {

	private static Context context;
	private static MyLocationManagerImpl myLocationManager;
	private static List<LocationListener> listeners = new ArrayList<LocationListener>();

	/**
	 * Listens to location updates.
	 */
	private static LocationListener locationListener = new LocationListener() {

		public void onLocationChanged(Location location) {

			PreferenceHelper.setMyLatitude(context, (float) location
					.getLatitude());
			PreferenceHelper.setMyLongitude(context, (float) location
					.getLongitude());

			for (Iterator<LocationListener> itr = listeners.iterator(); itr
					.hasNext();) {
				LocationListener listener = itr.next();
				listener.onLocationChanged(location);
			}
		}

		// Not used.
		public void onProviderDisabled(String provider) {
		}

		public void onProviderEnabled(String provider) {
		}

		public void onStatusChanged(String provider, int status, Bundle extras) {
		}
	};

	public static void setContext(Context context) {
		LocationHelper.context = context;
		myLocationManager = new MyLocationManagerImpl((LocationManager) context
				.getSystemService(Context.LOCATION_SERVICE));
		startUpdates();
	}

	public static void addListener(LocationListener locationListener) {
		if (!listeners.contains(locationListener)) {
			listeners.add(locationListener);
		}
	}

	public static void removeListener(LocationListener locationListener) {
		if (listeners.contains(locationListener)) {
			listeners.remove(locationListener);
		}
	}

	public static void startUpdates() {
		myLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
				0, 0, locationListener);

	}

	public static void stopUpdates() {
		myLocationManager.removeUpdates(locationListener);
	}

	/**
	 * Returns the distance between two GPS locations.
	 * 
	 * @param lat_a
	 * @param lng_a
	 * @param lat_b
	 * @param lng_b
	 * @return the distance in meters
	 */
	public static double gps2m(float lat_a, float lng_a, float lat_b,
			float lng_b) {
		float pk = (float) (180 / 3.14169);

		float a1 = lat_a / pk;
		float a2 = lng_a / pk;
		float b1 = lat_b / pk;
		float b2 = lng_b / pk;

		float t1 = FloatMath.cos(a1) * FloatMath.cos(a2) * FloatMath.cos(b1)
				* FloatMath.cos(b2);
		float t2 = FloatMath.cos(a1) * FloatMath.sin(a2) * FloatMath.cos(b1)
				* FloatMath.sin(b2);
		float t3 = FloatMath.sin(a1) * FloatMath.sin(b1);
		double tt = Math.acos(t1 + t2 + t3);

		return 6366000 * tt;
	}

	/**
	 * Starts the GEO address picker.
	 * 
	 * @param activity
	 * @param contactLookupUri
	 * @param requestCode
	 */
	public static void startGEOAddressPicker(Activity activity,
			Uri contactLookupUri, int requestCode) {

		Intent getGeoCodedAddressIntent = new Intent(
				GeocodedAddressChoiceList.SELECT, contactLookupUri, activity,
				GeocodedAddressChoiceList.class);
		activity.startActivityForResult(getGeoCodedAddressIntent, requestCode);

	}

}
